package com.dc.system.service.impl;

import com.dc.base.exception.BusinessException;
import com.dc.common.constants.ConstantsCommon;
import com.dc.common.model.BaseModel;
import com.dc.system.mapper.ApprovalMapper;
import com.dc.system.model.*;
import com.dc.system.service.ApprovalService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.regex.Pattern;

import static java.util.regex.Pattern.compile;

/**
 * @Description: ApprovalServiceImpl
 * @Author: ChenXueLi
 * @Date: 2018-05-04 11:54
 */
@Service
public class ApprovalServiceImpl implements ApprovalService {

    @Autowired
    private ApprovalMapper approvalMapper;

    /**
     * 添加一个模板
     * @param baseModel
     * @param approvalModel
     * @return
     */
    @Override
    public BaseModel addApprovalModel(BaseModel baseModel, ApprovalModel approvalModel, HttpServletRequest request) {
        SysUser sysUser = (SysUser)request.getSession().getAttribute(ConstantsCommon.LOGIN_INFO);
        // 初始化参数
        approvalModel.setCreate_time(new Date());
        approvalModel.setCreate_user_id(sysUser.getUser_id());
        approvalModel.setCreate_user_name(sysUser.getAccount());
        approvalModel.setUpdate_time(new Date());
        approvalModel.setUpdate_user_id(sysUser.getUser_id());
        approvalModel.setUpdate_user_name(sysUser.getAccount());

        // 执行添加
        int flag = approvalMapper.addApprovalModel(approvalModel);
        if(flag == 1) {
            baseModel.setCode(1);
            baseModel.setMessage("添加成功");
            baseModel.setData(approvalModel);
        }
        return baseModel;
    }

    /**
     * 添加一个分条件
     * @param baseModel
     * @param approvalProviso
     * @return
     */
    @Override
    public BaseModel addApprovalProviso(BaseModel baseModel, ApprovalProviso approvalProviso, HttpServletRequest request) {
        SysUser sysUser = (SysUser)request.getSession().getAttribute(ConstantsCommon.LOGIN_INFO);
        // 初始化参数
        approvalProviso.setCreate_time(new Date());
        approvalProviso.setCreate_user_id(sysUser.getUser_id());
        approvalProviso.setCreate_user_name(sysUser.getAccount());
        approvalProviso.setUpdate_time(new Date());
        approvalProviso.setUpdate_user_id(sysUser.getUser_id());
        approvalProviso.setUpdate_user_name(sysUser.getAccount());

        // 执行添加
        int flag = approvalMapper.addApprovalProviso(approvalProviso);
        if(flag == 1) {
            baseModel.setCode(1);
            baseModel.setMessage("添加成功");
            baseModel.setData(approvalProviso);
        }
        return baseModel;
    }

    /**
     * 添加一个流程
     * @param baseModel
     * @param approvalProcess
     * @return
     */
    @Override
    public BaseModel addApprovalProcess(BaseModel baseModel, ApprovalProcess approvalProcess, HttpServletRequest request) {
        // 获取到用户
        SysUser sysUser = (SysUser)request.getSession().getAttribute(ConstantsCommon.LOGIN_INFO);
        // 初始化参数
        approvalProcess.setCreate_time(new Date());
        approvalProcess.setCreate_user_id(sysUser.getUser_id());
        approvalProcess.setCreate_user_name(sysUser.getAccount());
        approvalProcess.setUpdate_time(new Date());
        approvalProcess.setUpdate_user_id(sysUser.getUser_id());
        approvalProcess.setUpdate_user_name(sysUser.getAccount());

        // 初始化流程
        initProcess(sysUser, approvalProcess);
        baseModel.setData(approvalProcess);

        // 添加数据库
        if(approvalProcess.getProcess_id() != null) {
            baseModel.setCode(1);
            baseModel.setMessage("添加成功");
            baseModel.setData(approvalProcess);
        }
        return baseModel;
    }

    /**
     * 审批操作
     * @param approvalHistory
     * @param baseModel
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public BaseModel examine(ApprovalHistory approvalHistory, BaseModel baseModel, HttpServletRequest request) throws Exception{
        Integer processId = approvalHistory.getProcess_id();
        Integer state = approvalHistory.getApproval_state();
        // 获取用户
        SysUser sysUser = (SysUser)request.getSession().getAttribute(ConstantsCommon.LOGIN_INFO);
        if (sysUser == null || sysUser.getAccount() == "" || "".equals(sysUser.getAccount())) {
            throw new BusinessException(-101, "获取用户失败！");
        }
        if(processId == null || processId < 0) {
            throw new BusinessException(-102, "获取流程编号失败！");
        }
        if(state == null || state < 0) {
            throw new BusinessException(-103, "获取状态编号失败！");
        }
        // 根据查询出审核的流程
        ApprovalProcess approvalProcess = approvalMapper.getApprovalProcessById(processId);
        if(approvalProcess == null) {
            throw new BusinessException(-104, "获取流程失败！");
        }
        // 获取当前历史表中的待审核用户列表
        List<ApprovalHistory> approvalHistories = approvalMapper.getApprovalHistoryNotExamineByProcessId(processId);
        if(approvalHistories == null || approvalHistories.size() <= 0) {
            throw new BusinessException(-105, "当前流程不需要审核操作！");
        }
        // 判断当前待审核用户表中是否有当前用户
        boolean flag = false;
        for(ApprovalHistory temp : approvalHistories) {
            if(sysUser.getAccount().equals(temp.getApprover())) {
                flag = true;
                break;
            }
        }
        if(!flag) {
            throw new BusinessException(-106, "当前流程不用未查询到需要您审批的流水！");
        }
        // 设置
        approvalHistory.setUpdate_time(new Date());
        approvalHistory.setUpdate_user_id(sysUser.getUser_id());
        approvalHistory.setUpdate_user_name(sysUser.getAccount());
        // 修改数据
        int effect = approvalMapper.updateApprovalHistory(approvalHistory);
        if(effect != 1) {
            throw new BusinessException(-107, "系统错误，修改审批状态失败！");
        }
        // 流程前进
        flag = executeNextStep(sysUser, approvalProcess);
        if(!flag) {
            baseModel.setCode(0);
            baseModel.setMessage("流程结束了");
            return baseModel;
        }
        baseModel.setCode(0);
        baseModel.setMessage("保存成功");
        return baseModel;
    }

    /**
     * 结束流程
     */
    public void overProcess(ApprovalProcess process) {
        if(isFinish(process)) {
            System.out.println("流程已经结束");
            return;
        }

        // 查询当前表中是否还有未审核的人员
        if(hasNotApprover()) {
            System.out.println("还有人员正在审核中");
            return;
        }

        // 判断当前流程是否还有人未审核，即查询当前审批有状态的历史中此审批编号的数据数是否与审批人数相匹配
        if(hasNextApprover(process)) {
            // 还有下一个
            process.setApproval_state(3);
            process.setApproval_result(null);
            return;
        }

        // 获取到需要同意的人数
        int requireNumber = process.getPass_approver_count();
        // 当前流程被同意的记录
        List<ApprovalHistory> approvalHistories = approvalMapper.getApprovalHistoryByIdByState(process.getProcess_id(), 1);
        // 被同意的人数
        int actualNumber = approvalHistories.size();
        // 设置状态
        setState(actualNumber >= requireNumber, process);
        // 执行修改流程操作
        approvalMapper.updateApprovalProcessState(process);
    }

    /**
     * 初始化流程（根据模板初始化）
     * @param sysUser 申请的用户
     */
    public void initProcess(SysUser sysUser, ApprovalProcess approvalProcess) {
        initProcess(null, sysUser, approvalProcess);
    }

    /**
     * 初始化流程（根据模板初始化）
     * @param index 可以为null，表示当前是第几个人在审批
     * @param sysUser 申请的用户
     */
    public void initProcess(Integer index, SysUser sysUser, ApprovalProcess process) {
        // 流程模板
        Map<String, Object> params = new HashMap<>();
        params.put("id", process.getApproval_model_id());
        ApprovalModel approvalModel = approvalMapper.getApprovalModelById(process.getApproval_model_id());
        process.setApproval_model(approvalModel);
        if(approvalModel == null) {
            System.out.println("审核模板数据错误");
            return;
        }

        // 参数赋值
        Integer approverType = approvalModel.getApprover_type();
        String approver = process.getApprover();
        Integer approvalOrder = approvalModel.getApproval_order();
        Integer passType = approvalModel.getApproval_pass_type();
        Double passProportion = approvalModel.getApproval_pass_proportion();

        if(approvalModel.getProviso_ids() != null || "".equals(approvalModel.getProviso_ids())) {
            // （先过滤分条件）过滤审核人（优先满足分条件但是只满足一个条件，优先级排序）
            String[] tempArray = approvalModel.getProviso_ids().split(",");
            List<Integer> provisoIds = new ArrayList<>();
            for(String str :tempArray) {
                provisoIds.add(Integer.valueOf(str));
            }
            List<ApprovalProviso> approvalProvisos = approvalMapper.getApprovalProvisoById(provisoIds);

            Map<String, Object> resultProviso = resultOfProviso(approvalProvisos, process.getApproval_proviso_value());

            boolean flag = (Boolean)resultProviso.get("result");

            // 满足条件了过滤
            if(flag) {
                // 获取满足的分条件
                ApprovalProviso approvalProviso = (ApprovalProviso)resultProviso.get("proviso");
                // 修改流程默认参数
                approverType = approvalProviso.getApprover_type();
                approver = approvalProviso.getApprover();
                approvalOrder = approvalProviso.getProviso_order();
                passType = approvalProviso.getApproval_pass_type();
                passProportion = approvalProviso.getApproval_pass_proportion();
            }
        }

        List<String> lists = new ArrayList<>();
        // 获取到审核人
        if(approverType == 0) {
            // 指定人
            lists = Arrays.asList(approver.split(","));
        }else if(approverType == 1) {
            // 指定职务
        }else if(approverType == 2) {
            // 指定部门
        }else {
            System.out.println("审核人类型错误");
            return;
        }
        List<SysUser> sysUsers = new ArrayList<>();
        for(String str : lists) {
            SysUser tempUser = new SysUser();
            tempUser.setName(str);
            sysUsers.add(tempUser);
        }

        // 计算审批需要通过的人数
        int count = sysUsers.size();
        if(count == 0) {
            // 不用审核系统默认通过
            return;
        }
        if(approvalOrder == 0) {
            // 顺序审核需要全部通过
            process.setPass_approver_count(count);
        }else {
            // 同步审核有自定义条件
            if(passType == 0) {
                process.setPass_approver_count(count);
            }else if(passType == 1) {
                process.setPass_approver_count(1);
            }else {
                Double re = Math.ceil(passProportion * count);
                process.setPass_approver_count(re.intValue());
            }
        }

        // 获取到第一个审批人开始执行审批
        SysUser tempUser = getFirstApprover(process);
        // 设置当前审核人的位置
        process.setCurrent_approver_order(0);
        if(index != null) {
            if(index < process.getApprover_list().size()) {
                tempUser = process.getApprover_list().get(index);
            }
            // 设置当前审核人的位置
            process.setCurrent_approver_order(index);
        }
        // 设置当前审核人
        process.setCurrent_approver(tempUser.getName());

        // 插入
        if(process.getProcess_id() != null) {
            approvalMapper.updateApprovalProcess(process);
        }else {
            approvalMapper.addApprovalProcess(process);
        }

        // 只有同步的时候才会进行循环
        if(approvalOrder == 1) {
            for(int i = 0; i < count; i++) {
                ApprovalHistory approvalHistory = new ApprovalHistory(sysUser);
                approvalHistory.initHistoryByProcess(process, i);
                // 执行插入
                approvalMapper.addApprovalHistory(approvalHistory);
            }
        }else {
            ApprovalHistory approvalHistory = new ApprovalHistory(sysUser);
            approvalHistory.initHistoryByProcess(process, process.getCurrent_approver_order());
            // 执行插入
            approvalMapper.addApprovalHistory(approvalHistory);
        }

        // 修改流程的状态为审批中

        // todo
    }

    /**
     * 重构流程（根据模板重置）
     * @param sysUser
     */
    public void refactorProcess(SysUser sysUser, ApprovalProcess approvalProcess) {
        initProcess(approvalProcess.getCurrent_approver_order(), sysUser, approvalProcess);
    }

    /**
     * 设置完成状态
     * @param flag true通过 false未通过
     */
    private void setState(boolean flag, ApprovalProcess approvalProcess) {
        // 结束状态
        approvalProcess.setApproval_state(4);
        if(flag) {
            // 通过
            approvalProcess.setApproval_state(1);
        }else {
            // 未通过
            approvalProcess.setApproval_state(0);
        }
    }

    /**
     * 执行下一阶段的审批操作
     */
    public Boolean executeNextStep(SysUser sysUser, ApprovalProcess approvalProcess) {
        // 判断流程是否结束
        if(isFinish(approvalProcess)) {
            System.out.println("流程已经结束");
            return false;
        }
        // 获取下一个审批人
        SysUser user = getNextApprover(approvalProcess);
        if(user == null) {
            // 没有下一个审批人了。执行结束
            return false;
        }else {
            approvalProcess.setCurrent_approver(user.getAccount());
            refactorProcess(sysUser, approvalProcess);
        }
        return true;
    }

    /**
     * 获取第一个审批人
     * @return
     */
    private SysUser getFirstApprover(ApprovalProcess approvalProcess) {
        SysUser user = null;
        if(approvalProcess.getApprover() != null) {
            user = approvalProcess.getApprover_list().get(0);
        }
        return user;
    }

    /**
     * 获取下一个审批人
     * @return
     */
    private SysUser getNextApprover(ApprovalProcess approvalProcess) {
        if(isFinish(approvalProcess)) {
            System.out.println("当前审批已经结束");
            return null;
        }
        SysUser user = null;
        for(int i = 0; i < approvalProcess.getApprover_list().size(); i++) {
            SysUser u = approvalProcess.getApprover_list().get(i);
            if(approvalProcess.getCurrent_approver().equals(u.getAccount()) && i < approvalProcess.getApprover_list().size() - 1) {
                user = approvalProcess.getApprover_list().get(i + 1);
                approvalProcess.setCurrent_approver_order(i + 1);
                break;
            }
        }
        return user;
    }

    /**
     * 获取最后一个审批人
     * @return
     */
    private SysUser getLastApprover(ApprovalProcess approvalProcess) {
        SysUser user = null;
        if(approvalProcess.getApprover() != null && approvalProcess.getApprover_list().size() > 0) {
            user = approvalProcess.getApprover_list().get(approvalProcess.getApprover_list().size() - 1);
        }
        return user;
    }

    /**
     * 判断还有没有下一个审批人
     * true 有
     * false 没有
     * @return
     */
    private Boolean hasNextApprover(ApprovalProcess approvalProcess) {
        int requireApprovalNumber = approvalProcess.getApprover_list().size();
        int currentApprovalNumber = approvalMapper.getApprovalHistoryByProcessId(null).size();
        if(currentApprovalNumber < requireApprovalNumber) {
            return false;
        }
        return true;
    }

    /**
     * 判断是否在历史审核表中还有未审核的人员
     * @return
     */
    private Boolean hasNotApprover() {
        List<ApprovalHistory> approvalHistories = approvalMapper.getApprovalHistoryByProcessId(null);
        if(approvalHistories.size() > 0) {
            return true;
        }
        return false;
    }

    /**
     * 判断审批是否已经结束
     * @return
     */
    private Boolean isFinish(ApprovalProcess approvalProcess) {
        if(approvalProcess.getApproval_state() == 4) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否是数字
     * @param str
     * @return
     */
    public boolean isInteger(String str) {
        Pattern pattern = compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(str).matches();
    }

    /**
     * 当前所有分条件的结果是否为真
     * @param approvalProvisos
     * @param value
     * @return
     */
    public  Map<String, Object> resultOfProviso(List<ApprovalProviso> approvalProvisos, String value) {
        /**
         * 优先高者满足即为满足（同一优先级的分条件必须全部满足才算真）
         */
        boolean resultBoolean = false;
        // 为分条件排序一次 todo
        Map<Integer, List<ApprovalProviso>> resultMap = new HashMap<>();
        // 从高开始判断
        for(int i = 0; i < approvalProvisos.size(); i++) {
            ApprovalProviso approvalProviso = approvalProvisos.get(i);
            List<ApprovalProviso> provisos = new ArrayList<>();
            if(resultMap.containsKey(approvalProviso.getProviso_order())) {
                provisos = resultMap.get(approvalProviso.getProviso_order());
            }
            // 一个一个判断
            boolean flag = false;
            switch(approvalProviso.getProviso_value_type()) {
                case "dept":
                    // 申请人部门满足要求（相等）
                    break;
                case "user":
                    // 申请人自身满足要求（相等）
                    break;
                case "job":
                    // 申请人职务满足要求（相等呢过）
                    break;
                case "number":
                    // 当前数字满足要求（比较大小）
                    // 将两边的值进行转换
                    // 流程的值
                    double number1 = Double.valueOf(value);
                    // 分条件要求的值
                    double number2 = Double.valueOf(approvalProviso.getProviso_value());
                    switch(approvalProviso.getRelation_operator()) {
                        case "<":
                            flag = number1 < number2;
                            break;
                        case ">":
                            flag = number1 > number2;
                            break;
                        case "=":
                            flag = number1 == number2;
                            break;
                        case ">=":
                            flag = number1 >= number2;
                            break;
                        case "<=":
                            flag = number1 <= number2;
                            break;
                        default:
                    }
                    break;
                default:
            }
            approvalProviso.setResult_flag(flag);
            provisos.add(approvalProviso);
            resultMap.put(approvalProvisos.get(i).getProviso_order(),provisos);
        }
        // 计算最终值
        int order = 0;
        LoopResult: for(Integer tempOrder : resultMap.keySet()) {
            List<ApprovalProviso> provisos = resultMap.get(tempOrder);
            resultBoolean = true;
            order = tempOrder;
            for(ApprovalProviso proviso : provisos) {
                if(!proviso.getResult_flag()) {
                    resultBoolean = proviso.getResult_flag();
                    break LoopResult;
                }
            }
        }
        Map<String, Object> map = new HashMap<>();
        // 最终结果
        map.put("result", resultBoolean);
        // 满足条件的proviso（只需要一个值）
        map.put("proviso", resultMap.get(order).get(0));
        return map;
    }
}
